/**
 * File:     wiidevicedriver.h
 * Authors:  Dominic Stalder, Thomas Bruederli
 *
 * Definition of the common interface for the platform specific implementations
 * of the wii device (wii balance board and wii controller) driver.
 *
 * This file is part of the Qt-based cross-platform Wii device driver.
 *
 * Copyright (C) 2009-2010, Dominic Stalder & Thomas Bruederli
 * Licensed under the GNU Lesser General Public License (LGPL) as published
 * by the Free Software Foundation at http://www.gnu.org/licenses/lgpl-3.0.txt
 *
 * $Id: wiidevicedriver.h 5 2010-03-03 09:10:12Z roundcube $
 */

#ifndef WIIDEVICEDRIVER_H_
#define WIIDEVICEDRIVER_H_

#include <QThread>
#include <QString>

// includes wiiuse header for wiiuse (windows/linux) only
#ifndef __APPLE__
		#include "wiiwin/wiiuseconnector.h"
#endif

// struct to represent the current device state
typedef struct
{
	float totalWeight;
	float topLeft;
	float topRight;
	float bottomRight;
	float bottomLeft;
	unsigned int buttonPressed;
	unsigned int connectionState;
	float batteyLevel;
} WiiDeviceState;

/**
 * Declaration for a cross-platform wii device driver.
 */
#ifndef __APPLE__
class WiiDeviceDriver : public QObject
{
	friend class WiiuseConnector;
#else
class WiiDeviceDriver : public QThread
{
#endif

	Q_OBJECT

public:
	enum THREADSTATE { STATE_NOTRUNNING, STATE_RUNNING };
	enum DEVICEMESSAGE { MESSAGE_SUCCESSFUL, MESSAGE_PRESSSYNCBUTTON, MESSAGE_SYNCBUTTONPRESSED, MESSAGE_DISCOVERYERROR, MESSAGE_LOSTCONNECTION, MESSAGE_BATTERYCHANGED, MESSAGE_CONNECTWINDOWS, MESSAGE_WRONGDEVICETYPE };
	enum DEVICETYPE { TYPE_NONE, TYPE_BALANCEBOARD, TYPE_CONTROLLER };
	enum CONNECTIONSTATE { STATE_NONE, STATE_NOTCONNECTED, STATE_CONNECTED, STATE_STOP };
	enum DEVICEBUTTON { BUTTON_NONE = 0x00, BUTTON_1 = 0x01, BUTTON_2 = 0x02, BUTTON_A = 0x04, BUTTON_B = 0x08, BUTTON_HOME = 0x10, BUTTON_PLUS = 0x20, BUTTON_MINUS = 0x40, BUTTON_UP = 0x80, BUTTON_DOWN = 0x0100, BUTTON_LEFT = 0x0200, BUTTON_RIGHT = 0x0400 };
	
public:
	WiiDeviceDriver(int);
	~WiiDeviceDriver(void);

private:
	void *wiiDevice;
	WiiDeviceState deviceState;
	int deviceType;
	int driverState;
	
protected:
	void run(void);
	
public:	
	void setConnectionState(int connectionState);
	int isConnected(void);
	WiiDeviceState& getDeviceState(void);
	void setInstruction(unsigned char instruction);
	void setLogMessage(QString logMessage);
	void setButtonPressed(int which, int state);
	void setAcceleration(double ax, double ay, double az);
	void setKilograms(float topLeft, float topRight, float bottomRight, float bottomLeft);
	void setBatteryLevel(float batteryLevel);
	
signals:
	void connectionStateChanged(int deviceType, int connectionState);
	void instructionChanged(int deviceType, const QString instruction, bool successful = false);
	void logMessageGenerated(QString logMessage, int deviceType = WiiDeviceDriver::TYPE_NONE, int connectionstate = WiiDeviceDriver::STATE_NONE);
	void buttonChanged(int which, int state);
	void orientationChanged(double roll, double pitch, double yaw);
	void kilogramsChanged(float topLeft, float topRight, float bottomRight, float bottomLeft, float totalWeight);
	
public slots:
	void stop(void);
	
/* For wiiuse only */
#ifndef __APPLE__
private:
	wiimote* mywiimote;
	void wiimoteConnect(wiimote*);
	void handleEvent(int);

public:
	// QThread compatibility
	void wait(void);
	int isRunning(void);
public slots:
	void start(void);
#endif
	
private:
	/**
	 * Static method to translate a integer message value to <code>QString</code>.
	 *
	 * @param   index  message index from the struct DEVICEMESSAGE
	 * @return  message text of the type <code>QString</code>
	 */
	static QString messageString(const unsigned char index)
	{
		QString out;

		switch (index)
		{
			case WiiDeviceDriver::MESSAGE_SUCCESSFUL:
				out = tr("Successully connected to the Wii Device!");
				break;
			case WiiDeviceDriver::MESSAGE_PRESSSYNCBUTTON:
				out = tr("Press the red SYNC-button!");
				break;
			case WiiDeviceDriver::MESSAGE_SYNCBUTTONPRESSED:
				out = tr("Red button pressed");
				break;
			case WiiDeviceDriver::MESSAGE_DISCOVERYERROR:
				out = tr("Make sure Bluetooth is available and enabled");
				break;
			case WiiDeviceDriver::MESSAGE_LOSTCONNECTION:
				out = tr("Lost connection to Wii Device");
				break;
			case WiiDeviceDriver::MESSAGE_BATTERYCHANGED:
				out = tr("Battery level changed");
				break;
			case WiiDeviceDriver::MESSAGE_CONNECTWINDOWS:
				out = tr("Connect via Bluetooth system settings");
				break;
			case WiiDeviceDriver::MESSAGE_WRONGDEVICETYPE:
				out = tr("This is not a Wii Balance Board!");
				break;
		}
		return out;
	}
};

#endif
